package com.hengpeng.itfints.controller.investInfo;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.persist.entity.AbstractEntity.BoolValue;
import com.hengpeng.common.util.MoneyUtil;
import com.hengpeng.common.util.StringHelper;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.TransCodeConstants;
import com.hengpeng.itfinbase.en.BorrowStatus;
import com.hengpeng.itfinbase.en.InvestStatus;
import com.hengpeng.itfinbase.en.RewardRedPacketStatus;
import com.hengpeng.itfinbase.en.RewardUseType;
import com.hengpeng.itfinbase.message.ResponseMessage;
import com.hengpeng.itfinbase.message.partner.InvestBorrowerDetail;
import com.hengpeng.itfinbase.message.partner.InvestInfoRequestMsg;
import com.hengpeng.itfinbase.message.partner.PartnerTransType;
import com.hengpeng.itfinbase.message.partner.RedUseRequestMsg;
import com.hengpeng.itfinbase.message.partner.TenderCancleRequest;
import com.hengpeng.itfinbase.message.partner.TenderCancleResponse;
import com.hengpeng.itfinbase.persist.Account;
import com.hengpeng.itfinbase.persist.BorrowInfo;
import com.hengpeng.itfinbase.persist.Reward;
import com.hengpeng.itfinbase.persist.RewardRedpacket;
import com.hengpeng.itfinbase.persist.UserInfo;
import com.hengpeng.itfints.constants.PartnerUtil;
import com.hengpeng.itfints.constants.TSConstants;
import com.hengpeng.itfints.controller.BaseController;
import com.hengpeng.itfints.controller.investInfo.vo.InvestInfoVo;
import com.hengpeng.itfints.tools.JsonUtils;
import com.hengpeng.itfints.tools.PageUtil;
import com.hengpeng.itfints.vo.MemberSession;

/**
 * <pre>
 * 投标控制器
 * </pre>
 * 
 * @author weiyuan
 * @version 1.0, 2015年5月28日
 */
@Controller
@RequestMapping("/investInfo")
public class InvestInfoController extends BaseController {
    /**
     * <pre>
     * 我的投资记录列表
     * </pre>
     * 
     * @param map
     * @param request
     * @return
     */
    @RequestMapping(value = "/myInvestList")
    public String myInvestList(ModelMap map, HttpServletRequest request, String curPage, InvestStatus investInfoStatus,
            String startInvestTime, String endInvestTime) {
        MemberSession session = getSessionMember(request);
        if (session == null) {
            return "/page/login/login.jsp";
        }
        UserInfo m = getSessionMember(request).getUser();
        UserInfo user = serviceFactory.getUserService().getUserById(m.getId());
        if (StringHelper.isEmpty(user.getTrustAccountId())) {
            return "redirect:/step_two_register_active.htm";
        }
        List<InvestInfoVo> dataList = serviceFactory.getInvestInfoService().queryMyInvestList(m.getId(),
                investInfoStatus, null, startInvestTime, endInvestTime);
        int currentPage = (!StringHelper.isEmpty(curPage) && curPage != null ? Integer.parseInt(curPage) : 1);
        PageUtil pUtil = new PageUtil(10, dataList.size(), currentPage);

        Account account = serviceFactory.getAccountService().getAccount(m.getId());
        map.put("myInvestList", dataList);
        map.put("account", account);
        map.put("investInfoStatus", investInfoStatus == null ? InvestStatus.LOANED : investInfoStatus);
        map.put("startTime", startInvestTime == null ? "" : startInvestTime);
        map.put("endTime", endInvestTime == null ? "" : endInvestTime);
        map.put("PageUtil", pUtil);
        return "/page/account/investlog/index.jsp";
    }

    /**
     * <pre>
     * 根据日历查看回款情况
     * </pre>
     * 
     * @param map
     * @param request
     * @param page
     * @param investInfoStatus
     * @param arrivalTime
     * @return
     */
    @RequestMapping(value = "/calInvestInfo")
    public String calInvestInfo(ModelMap map, HttpServletRequest request, String arrivalTime) {
        UserInfo m = getSessionMember(request).getUser();
        List<InvestInfoVo> dataList = serviceFactory.getInvestInfoService().queryMyInvestList(m.getId(),
                InvestStatus.LOANED, arrivalTime, null, null);
        map.put("myInvestList", dataList);
        return "/page/account/investlog/calInvestinfo.jsp";
    }

    /**
     * <pre>
     * 		 校验事项：
     * 		  1,投资人账户中必须有足够的资金进行投资。
     * 		  2,借款标的状态必须是：筹款中状态。
     * 		  3,投资金额必须在标的的最大投资金额和最小投资金额之间。
     * 		  4,校验投资金额是否已经超过剩余借款额度
     * 		 投资前操作：
     * 		  1,投资调用投资接口前，先占据投资额度(更新标的信息表中已募集金额,和已募集人数)
     * 		  2,设定投资支付时间限制，若超过时间限制还没有支付完成则释放投资额度。
     * 		  3,超过支付时间限制的投标，调用撤标接口。
     * 		  4,生成投资记录信息,状态为：投标中
     * 		 投资接口调用成功后操作：
     * 		  1,更新投资信息状态
     * 		  2,冻结投资人资金信息表中相关资金。
     * 		  3,添加资金流水表相关资金冻结流水。
     * 		  4,更新标的信息表中的已募集金额,已募集人数。
     * 		  5,判断标的是否已经金额达到募集金额，如果达到募集金额则设置标的状态为：募集结束
     * 		 投资接口调用失败后操作：
     * 		  1,释放投资额度
     * 		  2,更新投标信息状态为：失败
     * 		 投标实时返回和回调接口都需实现
     * </pre>
     * 
     * @param map
     * @param request
     * @param borrowInfoId
     *            标的id
     * @param investMoney
     *            投资金额
     * @param redPacketId
     *            使用的红包id
     * @return
     */
    @RequestMapping(value = "/doInvest")
    @ResponseBody
    public ServiceResult<ResponseMessage> doInvest(ModelMap map, HttpServletRequest request, String borrowInfoId,
            Long investMoney, Long redPacketId) {
        ServiceResult<ResponseMessage> result = new ServiceResult<ResponseMessage>();
        ResponseMessage response = new ResponseMessage();
        BorrowInfo borrowInfo = serviceFactory.getBorrowInfoService().getBorrowInfo(Long.parseLong(borrowInfoId),
                BorrowStatus.RAISE);
        MemberSession member = (MemberSession) request.getSession().getAttribute(TSConstants.CLIENT_SESSION_MEMBER);
        if (member == null) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("请先登录");
            result.setReturnValue(response);
            return result;
        }
        if (borrowInfo == null) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("标的不存在,或标的状态异常");
            result.setReturnValue(response);
            return result;
        }
        if (investMoney < (borrowInfo.getMinInvest() / 100) || investMoney > (borrowInfo.getMaxInvest() / 100)) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("投标金额不能小于最小投资额,并且不能大于最大投资额");
            result.setReturnValue(response);
            return result;
        }
        if ((investMoney * 100 - borrowInfo.getMinInvest()) % borrowInfo.getIncMoney() != 0) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("最小投标为:" + MoneyUtil.convertFenToYuan(borrowInfo.getMinInvest()) + "，增量金额必须为:"
                    + MoneyUtil.convertFenToYuan(borrowInfo.getIncMoney()) + "的整数倍");
            result.setReturnValue(response);
            return result;
        }
        if ((borrowInfo.getRaiseMoney() + investMoney * 100) > borrowInfo.getBorrowMoney()) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("投资额度已大于剩余融资额度");
            result.setReturnValue(response);
            return result;
        }
        if (member.getUser() == null) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("当前用户信息异常,请重新登录");
            result.setReturnValue(response);
            return result;
        }
        if (member.getUser().getIsInvestor() == BoolValue.NO) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("对不起,您不是投资人角色");
            result.setReturnValue(response);
            return result;
        }
        if (member.getUser().getId().equals(borrowInfo.getBorrowUserId())) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("对不起,您不能投资自己的借款标");
            result.setReturnValue(response);
            return result;
        }
        if (StringHelper.isEmpty(member.getUser().getTrustAccountId())) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("请您先开通托管账户");
            result.setReturnValue(response);
            return result;
        }
        /**
         * 红包可用性校验,根据红包对应的奖品类型进行判断
         */
        if (redPacketId != null) {
            RewardRedpacket rewardRedpacket = serviceFactory.getPersistService()
                    .get(RewardRedpacket.class, redPacketId);
            Reward reward = serviceFactory.getPersistService().get(Reward.class, rewardRedpacket.getRewardId());
            if (rewardRedpacket.getStatus() != RewardRedPacketStatus.CANUSE) {
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setMessage("该红包已使用或已过期。");
                result.setReturnValue(response);
                return result;
            }
            if (reward.getRewardUseType() == RewardUseType.CASH200) {// 200元起投
                if (investMoney < 200) {
                    result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                    result.setMessage("使用该红包最低起投金额为200元");
                    result.setReturnValue(response);
                    return result;
                }
            } else if (reward.getRewardUseType() == RewardUseType.MULTIPLE100) {// 100倍起投
                if (investMoney < rewardRedpacket.getMoney()) {
                    result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                    result.setMessage("使用该红包最低起投金额为红包面值的100倍");
                    result.setReturnValue(response);
                    return result;
                }
            }

            if ((rewardRedpacket.getMoney()) / 100 > investMoney.longValue()) {
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setMessage("红包金额已大于投资金额");
                result.setReturnValue(response);
                return result;
            }
            /**
             * 红包先使用掉
             */
            RedUseRequestMsg reqMsg = new RedUseRequestMsg();
            reqMsg.setRedPacketId(redPacketId);
            reqMsg.setTransType(TransCodeConstants.RedPacketCode.REDPACKET_USE);
            response = (ResponseMessage) serviceFactory.getProtFactory().remoteTrans(reqMsg);
            if (!RespCodeConstants.CommonCode.TRANS_SUC.equals(response.getRespCode())) {
                result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
                result.setMessage(response.getRespDesc());
                result.setReturnValue(response);
                return result;
            }
        }
        Account account = serviceFactory.getAccountService().getAccount(member.getUser().getId());
        if ((investMoney.doubleValue()) > (account.getBaseMoney() - account.getFreezeMoney()) / 100) {
            result.setCode(RespCodeConstants.CommonCode.TRANS_FAIL);
            result.setMessage("余额不足!");
            result.setReturnValue(response);
            return result;
        }

        InvestInfoRequestMsg reqMsg = new InvestInfoRequestMsg();
        List<InvestBorrowerDetail> borrowerDetails = new ArrayList<InvestBorrowerDetail>();
        InvestBorrowerDetail borrowerDetail = new InvestBorrowerDetail();
        borrowerDetail.setBorrowerCustId(borrowInfo.getBorrowUserTrustAccountId());
        borrowerDetail.setBorrowerAmt(MoneyUtil.convertFenToYuan(investMoney * 100));
        borrowerDetail.setBorrowerRate(TSConstants.CHAR_ONE);
        borrowerDetail.setProId(borrowInfo.getId().toString());
        borrowerDetails.add(borrowerDetail);
        reqMsg.setBorrowerDetails(JsonUtils.createGson().create().toJson(borrowerDetails));
        reqMsg.setTransAmt(String.valueOf(investMoney * 100));
        reqMsg.setRedPacketId(redPacketId);
        reqMsg.setUsrCustId(member.getUser().getTrustAccountId());
        reqMsg.setIsFreeze(TSConstants.CHAR_YES);
        reqMsg.setInvestUserName(member.getUser().getUserName());
        reqMsg.setInvestUserId(member.getUser().getId().toString());
        reqMsg.setBorrowInfoId(borrowInfo.getId().toString());
        reqMsg.setBorrowName(borrowInfo.getBorrowName());
        reqMsg.setPartnerTransType(PartnerTransType.InitiativeTender);
        reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
        reqMsg.setBgRetUrl(service_notify_url);
        reqMsg.setRetUrl(page_return_url);
        response = (ResponseMessage) serviceFactory.getProtFactory().remoteTrans(reqMsg);
        result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
        result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
        result.setReturnValue(response);
        result.setReturnObject(PartnerUtil.isTrustPattern());
        return result;
    }

    /**
     * <pre>
     * 撤标操作
     * </pre>
     * 
     * @param map
     * @param request
     * @param inverstId
     * @return
     */
    @RequestMapping(value = "/cancelInvest")
    @ResponseBody
    public ServiceResult<ResponseMessage> cancelInvest(ModelMap map, HttpServletRequest request, Long inverstId) {
        ServiceResult<ResponseMessage> result = new ServiceResult<ResponseMessage>();
        ResponseMessage response = new ResponseMessage();
        MemberSession member = (MemberSession) request.getSession().getAttribute(TSConstants.CLIENT_SESSION_MEMBER);
        if (member == null) {
            response.setOrderFormContent("撤标失败,原因如下：请先登录");
            result.setReturnValue(response);
            return result;
        }

        try {
            TenderCancleRequest tenderCancleRequest = new TenderCancleRequest();
            tenderCancleRequest.setUsrCustId(member.getUser().getTrustAccountId());
            tenderCancleRequest.setOrdId(String.valueOf(inverstId));
            tenderCancleRequest.setPartnerTransType(PartnerTransType.TenderCancle);
            tenderCancleRequest.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
            tenderCancleRequest.setBgRetUrl(service_notify_url);
            tenderCancleRequest.setRetUrl(page_return_url);
            TenderCancleResponse tenderCancleResponse = (TenderCancleResponse) serviceFactory.getProtFactory()
                    .remoteTrans(tenderCancleRequest);
            response.setOrderFormContent(tenderCancleResponse.getRespDesc());
            result.setReturnValue(response);
            return result;
        } catch (Exception e) {
            response.setOrderFormContent("撤标失败,原因如下:" + e.getMessage());
            result.setReturnValue(response);
            return result;
        }

    }
}
